﻿using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
using FluentIoC.Configuration;

namespace FluentIoC.Helpers
{
    public static class DelegateHelpers
    {
        private static ProxyGenerator _proxyGenerator = new ProxyGenerator();

        public static string GetMethodName<T>(this Func<T, object> func)
        {
            func(GetProxy<T>());

            if (MethodInterceptor.Invocation == null)
            {
                throw new FluentIoCException(
                    "Could not retrieve the method/property name, probably because the method/property is not virtual"
                );
            }

            return MethodInterceptor.Invocation.Method.Name
                .Replace("get_", string.Empty)
                .Replace("set_", string.Empty);
        }

        public static IInvocation GetInvocationInfomation<T>(this Func<T, object> func)
        {
            func(GetProxy<T>());

            if (MethodInterceptor.Invocation == null)
            {
                throw new FluentIoCException(
                    "Could not retrieve the method/property name, probably because the method/property is not virtual"
                );
            }

            return MethodInterceptor.Invocation;
        }

        private static T GetProxy<T>()
        {
            var type = typeof(T);

            T proxy;

            if (type.IsClass)
            {
                proxy = (T)_proxyGenerator.CreateClassProxy(type, new MethodInterceptor());
            }
            else if (type.IsInterface)
            {
                proxy = (T)_proxyGenerator.CreateInterfaceProxyWithoutTarget(type, new MethodInterceptor());
            }
            else
            {
                throw new NotImplementedException();
            }

            return proxy;
        }
    }
}
